/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package pl.droidsonroids.gif.gifsample.slice;

import pl.droidsonroids.gif.gifsample.LogUtil;
import pl.droidsonroids.gif.gifsample.ResourceTable;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.utils.Rect;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.global.resource.RawFileDescriptor;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Size;
import pl.droidsonroids.gif.GifDecoder;
import pl.droidsonroids.gif.InputSource;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * DecoderSlice
 */
public class DecoderSlice extends AbilitySlice {
    private static final String TAG = DecoderSlice.class.getName();
    private static final int DEFAULT_TWO = 2;
    private static final int TIME_MS = 5000;
    ComponentContainer rootLayout;
    Text decoderLoadingTextView;
    Image decoderImageView;
    PixelMap pixelMap;
    EventHandler handler;
    Runnable runnable;
    private List frames = Collections.emptyList();
    private List durations = Collections.emptyList();
    private int currentFrameIndex = 0;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        initLayout();
    }

    private void initLayout() {
        LogUtil.debug(TAG, "initLayout");
        handler = new EventHandler(EventRunner.getMainEventRunner());
        rootLayout = (ComponentContainer) LayoutScatter.getInstance(this)
                .parse(ResourceTable.Layout_layout_decoder, null, false);
        decoderLoadingTextView = (Text)rootLayout.findComponentById(ResourceTable.Id_decoderLoadingTextView);
        decoderImageView = (Image)rootLayout.findComponentById(ResourceTable.Id_decoderImageView);
        super.setUIContent(rootLayout);
    }

    @Override
    public void onActive() {
        super.onActive();
        initView();
    }

    private void initView() {
        RawFileDescriptor rawFileDescriptor = null;
        GifDecoder decoder = null;
        final List frameList = (List)(new ArrayList());
        final List durationList = (List)(new ArrayList());
        try {
            rawFileDescriptor = getResourceManager()
                    .getRawFileEntry("entry/resources/rawfile/anim_flag_ok_large.gif").openRawFileDescriptor();
        } catch (IOException e) {
            LogUtil.error(TAG, "IOException in getRawFileEntry");
        }
        try {
            decoder = new GifDecoder(new InputSource.AssetFileDescriptorSource(rawFileDescriptor));
        } catch (IOException e) {
            LogUtil.error(TAG, "IOException");
        } catch (DataAbilityRemoteException e) {
            LogUtil.error(TAG, "DataAbilityRemoteException");
        }
        for (int val = 0; val < decoder.getNumberOfFrames(); val++) {
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            initializationOptions.pixelFormat = ohos.media.image.common.PixelFormat.ARGB_8888;
            initializationOptions.size = new Size(decoder.getWidth(), decoder.getHeight());
            pixelMap = PixelMap.create(initializationOptions);
            decoder.seekToFrame(val, pixelMap);
            frameList.add(pixelMap);
            durationList.add(decoder.getFrameDuration(val));
        }
        decoder.recycle();
        this.frames = frameList;
        this.durations = durationList;
        if (!frames.isEmpty()) {
            startAnimation();
        }
        decoderLoadingTextView.setVisibility(Component.INVISIBLE);
    }

    @Override
    protected void onStop() {
        handler.removeTask(runnable);
        super.onStop();
    }

    private void startAnimationUsingAnimator() {
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(TIME_MS);
        animatorValue.setCurveType(Animator.CurveType.LINEAR);
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            int val = 1;
            @Override
            public void onUpdate(AnimatorValue animatorValue, float value) {
                int index = ((val % DEFAULT_TWO) == 0) ? 0 : 1;
                val++;
                Rect rect = new Rect(0, 0, decoderImageView.getWidth(), decoderImageView.getHeight());
                PixelMapElement pixelMapElement = new PixelMapElement((PixelMap)frames.get(index));
                pixelMapElement.setBounds(rect);
                decoderImageView.setImageElement(pixelMapElement);
            }
        });
        animatorValue.start();
    }

    private void startAnimation() {
        decoderImageView.setImageElement(createElementfromPixelMap());
        long duration = (long)((Number)this.durations.get(currentFrameIndex)).intValue();
        final Runnable task = new Runnable() {
            /**
             * Run method
             */
            public void run() {
                advanceAnimation();
            }
        };
        handler.postTask(task, duration);
    }

    private PixelMapElement createElementfromPixelMap() {
        Rect rect = new Rect(0, 0, decoderImageView.getWidth(), decoderImageView.getHeight());
        PixelMapElement pixelMapElement = new PixelMapElement((PixelMap)frames.get(currentFrameIndex));
        pixelMapElement.setBounds(rect);
        return pixelMapElement;
    }

    private void advanceAnimation() {
        currentFrameIndex++;
        currentFrameIndex %= this.frames.size();
        decoderImageView.setImageElement(createElementfromPixelMap());
        long duration = (long)((Number)this.durations.get(currentFrameIndex)).intValue();
        runnable = new Runnable() {
            /**
             * run method
             */
            public void run() {
                advanceAnimation();
            }
        };
        handler.postTask(runnable, duration);
    }
}
